package hash;

import java.awt.EventQueue;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFileChooser;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JSeparator;
import javax.swing.JCheckBox;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.JProgressBar;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;


public class HasherGUI {

	static final boolean DEBUG = false;
	
	private JFrame frame;
	private JTextField fileField;
	private JTextField md5Field;
	private JTextField sha1Field;
	private JButton btnNewButton_1;
	private JButton btnClear;
	private JCheckBox chckbxMd;
	private JCheckBox chckbxSha;
	private JCheckBox chckbxCompare;
	private JCheckBox chckbxDigest;	
	
	private JProgressBar progressBar;
	
	private JFileChooser fc;	
	private File file;	
	
	private Hasher hasher;
	private boolean digest;
	private boolean isSet;
	private JMenuBar menuBar;
	private JMenu mnFile;
	private JMenuItem mntmSaveTo;
	private JMenu mnHelp;
	private JMenuItem mntmHelpContent;
	private JMenuItem mntmAboutJhasher;
	private JMenuItem mntmQuit;
	private JMenuItem mntmLoadChecksum;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				try
				{
					HasherGUI window = new HasherGUI();
					window.frame.setVisible(true);
				} 
				catch (Exception e) { e.printStackTrace(); }
			}
		});
	}

	/**
	 * Create the application.
	 */
	public HasherGUI()
	{
		hasher = new Hasher();
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize()
	{		
		frame = new JFrame("J-Hasher");
		frame.setBounds(100, 100, 400, 350);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
		
		fc = new JFileChooser();
		
		JPanel panel = new JPanel();
		frame.getContentPane().add(panel);
		
		JLabel lblNewLabel = new JLabel("File");
		
		fileField = new JTextField();
		fileField.setColumns(10);
		
		JButton btnNewButton = new JButton("Select");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0)
			{				
		        int returnVal = fc.showOpenDialog(frame);
		        if (returnVal == JFileChooser.APPROVE_OPTION)
		        {
		            file = fc.getSelectedFile();
		            fileField.setText( file.toString() );		           
		        }
		        else
		        {
		        	clear();
		        	file = null;
		        	fileField.setText("");		        	
		        }
			}
		});
		
		JSeparator separator = new JSeparator();
		
		chckbxMd = new JCheckBox("MD5");		
		chckbxSha = new JCheckBox("SHA1");
		
		md5Field = new JTextField();
		md5Field.setColumns(10);
		
		sha1Field = new JTextField();
		sha1Field.setColumns(10);
		
		btnNewButton_1 = new JButton("Hash");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{				
				progressBar.setIndeterminate(true);
				clear();
				if ( file != null && file.exists() )
				{
					new Thread() {
						public void run()
						{
							ResultWrapper results = hasher.createChecksum( file );							
							if (digest)
							{
								if (DEBUG) System.out.println("Digest");	
								progressBar.setIndeterminate(false);
								md5Field.setText( results.getMD5() );
								sha1Field.setText( results.getSHA1() );
								isSet = true;
							}
							else
							{
								if (DEBUG) System.out.println("Compare");
								progressBar.setIndeterminate(false);
								if ( md5Field.getText().equals( results.getMD5() ) )
								{
									if (DEBUG) System.out.println("Match: MD5");
									chckbxMd.setEnabled(true);
									chckbxMd.setSelected(true);
								}
								if ( sha1Field.getText().equals( results.getSHA1() ) )
								{
									if (DEBUG) System.out.println("Match: SHA1");
									chckbxSha.setEnabled(true);
									chckbxSha.setSelected(true);
								}
							}
						}
					}.start();
				}
				else {
					if (DEBUG) System.out.println("FIle does not exist.");
				}
			}
		});
		
		btnClear = new JButton("Clear");
		btnClear.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{				
				fileField.setText("");
				clearFields();
				clear();
			}
		});
		
		JPanel panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Mode", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		progressBar = new JProgressBar();
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_panel.createSequentialGroup()
					.addGroup(gl_panel.createParallelGroup(Alignment.TRAILING)
						.addGroup(gl_panel.createSequentialGroup()
							.addContainerGap()
							.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(chckbxMd)
									.addPreferredGap(ComponentPlacement.UNRELATED)
									.addComponent(md5Field, GroupLayout.DEFAULT_SIZE, 311, Short.MAX_VALUE))
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(btnClear)
									.addGap(18)
									.addComponent(btnNewButton_1)
									.addGap(18)
									.addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE))
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(lblNewLabel)
									.addPreferredGap(ComponentPlacement.RELATED)
									.addComponent(fileField, GroupLayout.DEFAULT_SIZE, 337, Short.MAX_VALUE))
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(btnNewButton, GroupLayout.PREFERRED_SIZE, 115, GroupLayout.PREFERRED_SIZE)
									.addGap(18)
									.addComponent(panel_1, GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE))))
						.addGroup(gl_panel.createSequentialGroup()
							.addGap(12)
							.addComponent(chckbxSha)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(sha1Field, GroupLayout.DEFAULT_SIZE, 311, Short.MAX_VALUE))
						.addGroup(gl_panel.createSequentialGroup()
							.addContainerGap()
							.addComponent(separator, GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE)))
					.addContainerGap())
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addGap(20)
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblNewLabel)
						.addComponent(fileField, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE))
					.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_panel.createSequentialGroup()
							.addGap(18)
							.addComponent(btnNewButton))
						.addGroup(gl_panel.createSequentialGroup()
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 76, GroupLayout.PREFERRED_SIZE)))
					.addGap(18)
					.addComponent(separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(md5Field, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
						.addComponent(chckbxMd))
					.addGap(19)
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(sha1Field, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
						.addComponent(chckbxSha))
					.addGap(18)
					.addGroup(gl_panel.createParallelGroup(Alignment.LEADING, false)
						.addComponent(progressBar, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(btnNewButton_1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(btnClear, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
					.addGap(25))
		);
		
		chckbxCompare = new JCheckBox("Compare");
		chckbxCompare.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				if (chckbxCompare.isSelected())
				{	
					if (DEBUG) System.out.println("Checked: Compare");
					chckbxDigest.setSelected(false);
					digest = false;
					clear();
				}
				else
				{
					if (DEBUG) System.out.println("UnChecked: Compare");
					chckbxDigest.setSelected(true);
					digest = true;
					clearFields();
					clear();
				}
			}
		});
		panel_1.add(chckbxCompare);
		
		chckbxDigest = new JCheckBox("Digest");
		chckbxDigest.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{				
				if (chckbxDigest.isSelected()) 
				{				
					if (DEBUG) System.out.println("Checked: Digest");
					chckbxCompare.setSelected(false);
					digest = true;
					clearFields();
					clear();
				}
				else
				{
					if (DEBUG) System.out.println("UnChecked: Digest");
					chckbxCompare.setSelected(true);
					digest = false;
					clear();
				}
			}
		});
		panel_1.add(chckbxDigest);
		panel.setLayout(gl_panel);		

		chckbxCompare.setSelected(true);
		
		menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);
		
		mnFile = new JMenu("File");
		menuBar.add(mnFile);
		
		mntmSaveTo = new JMenuItem("Save As...");
		mntmSaveTo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				if (isSet)
				{					
					int returnVal = fc.showSaveDialog(frame);
					if (returnVal == JFileChooser.APPROVE_OPTION)
					{
						File saveFile = fc.getSelectedFile();
						try
						{							
							BufferedWriter out = new BufferedWriter(new FileWriter(saveFile));
							if (DEBUG) System.out.println("Writing to File");
							
							out.write( Checksums.buildTags(md5Field.getText(), Checksums.MD5) );							
							out.newLine();							
							out.write( Checksums.buildTags(sha1Field.getText(), Checksums.SHA1) );
							
							if (out != null)out.close();							
						}
						catch (IOException e1) { e1.printStackTrace(); }
					}
					else
					{						
						if (DEBUG) System.out.println("Checksums not saved.");
					}
				}
			}
		});
		
		mntmLoadChecksum = new JMenuItem("Load Checksum");
		mntmLoadChecksum.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
		        int returnVal = fc.showOpenDialog(frame);
		        if (returnVal == JFileChooser.APPROVE_OPTION)
		        {
		        	try
		        	{
		        		if (DEBUG) System.out.println("Reading checksum file.");
		        		file = fc.getSelectedFile();		           
						BufferedReader br = new BufferedReader(new FileReader(file));
						String inLine;
						
						while ( (inLine = br.readLine()) !=null )
						{							
							switch( Checksums.matchType(inLine) )
							{
							case MD5:								
								if (DEBUG) System.out.println("MD5 Checksum: " + inLine);								
								md5Field.setText( Checksums.stripTags( inLine ) );
								break;								
							case SHA1:								
								if (DEBUG) System.out.println("SHA1 Checksum: " + inLine);
								sha1Field.setText( Checksums.stripTags( inLine ) );
								break;
							}
						}
						if (br != null)br.close();
					}
		        	catch (FileNotFoundException e1) { e1.printStackTrace(); }
		        	catch (IOException e1) { e1.printStackTrace(); }
		        }
								
			}
		});
		mnFile.add(mntmLoadChecksum);
		mnFile.add(mntmSaveTo);
		mnFile.addSeparator();
		
		mntmQuit = new JMenuItem("Quit");
		mntmQuit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				System.exit(0); 
			}
		});
		mnFile.add(mntmQuit);
		
		mnHelp = new JMenu("Help");
		menuBar.add(mnHelp);
		
		mntmHelpContent = new JMenuItem("Help Content");
		mntmHelpContent.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{				
				try 
				{
					Help dialog = new Help();
					dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					dialog.setVisible(true);
				}
				catch (Exception exp) { exp.printStackTrace(); }
			}
		});
		mnHelp.add(mntmHelpContent);
		
		mntmAboutJhasher = new JMenuItem("About JHasher");
		mntmAboutJhasher.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{				
				try 
				{
					About dialog = new About();
					dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					dialog.setVisible(true);
				}
				catch (Exception exp) { exp.printStackTrace(); }
			}
		});
		mnHelp.add(mntmAboutJhasher);
		digest = false;
		clearFields();
		clear();		
	}
	
	
	void clear()
	{
		chckbxSha.setSelected(false);
		chckbxSha.setEnabled(false);
		chckbxMd.setSelected(false);
		chckbxMd.setEnabled(false);
	}
	
	
	void clearFields()
	{
		isSet = false;
		md5Field.setText("");
		sha1Field.setText("");
	}

}
